package drep;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.Socket;

/**
 * Universidad Simón Bolívar
 * Curso de Redes I - Taller
 * Profesor: Ricardo Gonzalez
 * Trimestre Enero-Marzo 2011
 *
 * Proyecto 2 RD
 *
 * @author Grupo 9
 * @author Richard Simoes Ferreira
 * @author Ricardo Tocco
 *
 * @version 1.0
 *
 */
public class ErrorHandler {
    //Permite manejar los errores de drep

    private ControlDrep control;

    /**
     * Constructor de la clase
     */
    public ErrorHandler (){
        control = null;
    }

    public ErrorHandler (ControlDrep c){
        this.control = c;
    }

    /**
     *  Obtiene la estructura de control drep que está siendo utilizada por
     * el errorHandler
     * @return  la estructura de control que esta utilizando errorHandler
     */
    public ControlDrep getControlDrep(){
        return this.control;
    }

    /**
     * Establece la estructura de control drep que usa errorHandler
     * @param c Estructura de control drep
     */
    public void setControl(ControlDrep c){
        this.control = c;
    }

    /**
     * Imprime por salida estandar la ayuda de invocacion del programa,
     * si el mismo fue mal invocado y termina el programa.
     * @return void
     */

    public static void imprimirAyudaUsage () {
        System.err.println("\n+---- USAGE ----+\n\n");
        System.err.println("drep -c <puerto local clientes> -h <host dmon> " +
                "-p <puerto dmon> -d <rdirectorio>\n\n");
        System.exit(-1);
    }

    /**
     * Error de argumentos
     */
    public void argumentosInvalidos (){
        System.err.println("ErrorHandler_Drep: Se ha introducido un numero" +
                " inválido de" +
                " argumentos o algún argumento es desconocido");
        imprimirAyudaUsage();
    }
    /**
     * Redifinición una o más veces de un mismo argumento
     * @param parametro Argumento redefinido una o más veces
     */
    public void redifinicionArgumento (String parametro){
        System.err.println("ErrorHandler_Drep: Se ha redefinido "+parametro+
                " mas de una vez");
        imprimirAyudaUsage();
    }

    /**
     * Error de parametros desconocidos o inválidos
     */
    public void parametroInvalido(){
        System.err.println("ErrorHandler_Drep: Uno o más parámetros" +
                " inválidos se han introducido");
        imprimirAyudaUsage();
    }

     /**
     * Error de verificación de existencia del directorio <rdirectorio>
      * de entrada
     */
    public void directorioNoExiste(){
        System.err.println("ErrorHandler_Drep: El directorio <rdirectorio>" +
                " (-d) introducido por el usuario no existe" +
                "o no ha podido ser localizado, por favor introduzca una " +
                "direccion absoluta válida");
        System.exit(-1);
    }

     /**
     * Error al momento de abrir el socket servidor
     * @param e         Excepcion del sistema
     * @param puerto    Puerto al cual no ha podido establecer conexion
     */
    public void errorPuertoServerConnect(IOException e, int puerto){
        System.err.println("ErrorHandler_Drep: No se ha podido abrir el " +
                "socket en el puerto "+puerto);
        System.exit(-1);
    }

    /**
     * Error al momento de cerrar el socket servidor
     * @param e         Excepcion del sistema
     */
    public void errorSocketServerDisconnect(IOException e){
        System.err.println("ErrorHandler_Drep: No se ha podido cerrar el " +
                "socket servidor correctamente");
        System.exit(-1);
    }

    /**
     * Error al momento establecer la conexion con el socket bien conocido
     * del servidor dmon
     * @param e         Excepcion del sistema
     * @param puerto    Puerto al cual no ha podido establecer conexion
     */
    public void errorPuertoClientConnect(IOException e, int puerto){
        System.err.println("ErrorHandler_Drep: No se ha podido abrir el " +
                "socket en el puerto "+puerto);
        System.exit(-1);
    }

    /**
     * Error al momento cerrar la conexion con el socket bien conocido
     * del servidor dmon
     * @param e         Excepcion del sistema
     */
    public void errorSocketClientDisconnect(IOException e){
        System.err.println("ErrorHandler_Drep: No se ha podido cerrar el " +
                "socket de conexion con drep correctamente");
        System.exit(-1);
    }

    /**
     * Ayuda con los comandos aceptados por consola
     */
    public static void imprimirAyudaConsola(){
        System.out.println("Consola Drep v1.0");
        System.out.println("Comandos :\n-------------");
        System.out.println("ldir \ncat <nombre_archivo>\nhelp\n--help\nq");
    }

    /**
     * El comando introducido por consola no se reconoce
     * @param comando   Comando que no ha podido ser reconocido
     */
    public void errorComandoDesconocido(String comando){
        System.err.println("ErrorHandler_Drep: El comando introducido *"+
                comando+"* no es reconocido por favor intente de nuevo");
        imprimirAyudaConsola();

    }

    /**
     * Error de lectura en Consola
     * @param e         Excepcion del sistema
     * @param control   ControlDrep del drep
     */
    public void errorLecturaConsola(IOException e, ControlDrep control){
        System.err.println("ErrorHandler_Drep: Se ha producido un " +
                "error de lectura en consola");
        control.cerrarSesion();
        System.exit(-1);
    }

    /**
     * Error al momento de leer mensaje del socket proviente del
     * dmon correspondiente
     * @param c         ClientConnection de drep
     */
    public void errorBufferGetLinea(ClientConnection c){
        System.out.println("ErrorHandler_Drep: Atención parece que el" +
                " servidor dmon se encuentra caído, por lo que no es posible" +
                "tramitar más solicitudes de clientes dcli");
                    System.out.println("Finalizando drep....");
    }

    /**
     * Dmon caido, terminamos Drep
     * @param c         Socket de drep
     */
    public void terminarDrep(Socket s){
        try {
            s.close();
        } catch (IOException ex) {
            errorCerrarCliente(ex);
            this.control.setStatusOff();
            System.exit(-1);
        }
        this.control.setStatusOff();
        System.exit(-1);
    }

    public void errorCerrarCliente(IOException e){
        System.err.println("ErrorHandler_Drep: No ha sido posible cerrar" +
                " correctamente el socket del cliente Dcli");
    }

    /**
     * Error al momento de leer mensaje del socket proviente del
     * dcli correspondiente
     * @param control         ControlDrep de drep
     * @param cliente         Socket Cliente dcli
     */
    public void errorBufferGetLineaDcli(ControlDrep control, Socket cliente){
         System.out.println("ErrorHandler_Drep: Atención el cliente " +
                " se ha desconectado de forma no esperada.... ");
         System.out.println("Finalizando sesion dcli....");
    }

    /**
     * Error al momento de cerrar el BufferReader del socket del
     * dmon correspondiente
     * @param e         Excepcion del sistema
     */
    public void errorCloseBufferGetLinea(IOException e){
        System.err.println("ErrorHandler_Drep: Problemas cerrando el" +
                    "BufferedReader de GetLinea de Dmon");
    }

    /**
     * Error al momento de cerrar el BufferReader del socket del
     * dcli correspondiente
     * @param e         Excepcion del sistema
     */
    public void errorCloseBufferGetLineaDcli(IOException e){
        System.err.println("ErrorHandler_Drep: Problemas cerrando el" +
                    "BufferedReader de GetLinea de Dcli");
    }

    /**
     * Error al momento de abrir el BufferedReader para leer mensaje del
     * socket proviente del dmon correspondiente
     * @param c         ClientConnection de drep
     */
    public void errorGetLinea(ClientConnection c){
        System.err.println("ErrorHandler_Drep: No ha sido posible abrir" +
                " correctamente el BufferedReader para recibir el mensaje " +
                "esperado del servidor dmon, puede que este caído o haya" +
                "cerrado su socket de comunicación");
    }

    /**
     * Error al momento de abrir el BufferedReader para leer mensaje del
     * socket proviente del dcli correspondiente
     * @param control       ControlDrep
     * @param cliente       Socket del cliente dcli
     */
    public void errorGetLineaDcli(ControlDrep control, Socket cliente){
        System.err.println("ErrorHandler_Drep: No ha sido posible abrir" +
                " correctamente el BufferedReader para recibir el mensaje " +
                "esperado del cliente dcli, puede que este caído o haya" +
                "cerrado su socket de comunicación");
    }

    /**
     * Error al momento de abrir el PrintWriter para enviar el mensaje al
     * socket del dmon correspondiente
     * @param c         ClientConnection del drep
     * @param e         Error del sistema
     */
    public void errorSendLinea(ClientConnection c, IOException e){
        System.err.println("ErrorHandler_Drep: No ha sido posible abrir" +
                " correctamente el PrintWriter para enviar el mensaje " +
                "esperado al servidor dmon, puede que este caído o haya" +
                "cerrado su socket de comunicación");
    }

    /**
     * Error al momento de abrir el PrintWriter para enviar el mensaje al
     * socket del dcli correspondiente
     * @param control         ControlDrep del drep
     * @param e         Error del sistema
     */
    public void errorSendLineaDcli(ControlDrep control, IOException e){
        System.err.println("ErrorHandler_Drep: No ha sido posible abrir" +
                " correctamente el PrintWriter para enviar el mensaje " +
                "esperado al cliente dcli, puede que este caído o haya" +
                "cerrado su socket de comunicación");
    }

    /**
     * Error al momento de enviar el mensaje de solicitud newDrep al dmon
     */
    public void errorSolicitudIniciarSesion(){
        System.err.println("ErrorHandler_Drep: No ha sido posible enviar " +
                "solicitud IniciarSesion correctamente al dmon " +
                "correspondiente, intentelo de nuevo mas tarde");
    }

    /**
     * Error al momento de enviar el mensaje de solicitud disconnectDcli
     * al dmon
     */
    public void errorSolicitudCerrarSesion(){
        System.err.println("ErrorHandler_Drep: No ha sido posible enviar " +
                "solicitud CerrarSesion correctamente al drep " +
                "correspondiente, intentelo de nuevo mas tarde");
    }

    /**
     * Error al momento de enviar el mensaje de solicitud newDcli al dmon
     */
    public void errorSolicitudIniciarSesionDcli(){
        System.err.println("ErrorHandler_Drep: No ha sido posible enviar " +
                "solicitud IniciarSesionDcli (newDcli) correctamente al dmon " +
                "correspondiente, intentelo de nuevo mas tarde");
    }

    /**
     * Error al momento de enviar el mensaje de solicitud disconnectDcli al dmon
     */
    public void errorSolicitudCerrarSesionDcli(){
        System.err.println("ErrorHandler_Drep: No ha sido posible enviar " +
                "solicitud CerrarSesionDcli (newDcli) correctamente al dmon " +
                "correspondiente, intentelo de nuevo mas tarde");
    }

    /**
     * Error al momento de enviar el mensaje de solicitud nrep al dmon
     */
    public void errorSolicitudNrep(){
        System.err.println("ErrorHandler_Drep: No ha sido posible enviar " +
                "solicitud nrep correctamente al drep correspondiente," +
                " intentelo de nuevo mas tarde");
    }

    /**
     * Transferencia de archivo no satisfactoria al ejecutar el comando
     * sube
     */
    public void errorTransferenciaIncompletaSube(){
        System.err.println("ErrorHandler_Drep: La transferencia no se " +
                "ha podido ejecutar de manera correcta (Comando Sube)");
    }

    /**
     * Transferencia de archivo no satisfactoria al ejecutar el comando
     * sube archivo no existe en ldir*
     * @param e         Excepcion lanzada por el sistema
     * @param archivo   Nombre del archivo no encontrado
     */
    public void errorCreacionArchivoSube(FileNotFoundException e, String archivo){
        System.err.println("ErrorHandler_Drep: El archivo *"+archivo+
                "* no ha podido ser creado en rdir (Comando Sube)");
    }

    /**
     * Transferencia de archivo no satisfactoria al ejecutar el comando
     * sube excepcion IO
     * @param e Excepcion lanzada por el sistema
     */
    public void errorTransferenciaSube(IOException e){
        System.err.println("ErrorHandler_Drep: Se ha producido un " +
                "error no esperado en la transferencia (Comando Sube)");
    }

    /**
     * Transferencia de archivo no satisfactoria al ejecutar el comando
     * baja
     */
    public void errorTransferenciaIncompletaBaja(){
        System.err.println("ErrorHandler_Drep: La transferencia no se " +
                "ha podido ejecutar de manera correcta (Comando Baja)");
    }

    /**
     * Transferencia de archivo no satisfactoria al ejecutar el comando
     * baja archivo no existe en rdir*
     * @param archivo   Nombre del archivo no encontrado
     */
    public void errorArchivoNoExisteBaja(String archivo){
        System.err.println("ErrorHandler_Drep: El archivo *"+archivo+
                "* no existe en rdir (Comando Baja)");
    }

    /**
     * Transferencia de archivo no satisfactoria al ejecutar el comando
     * baja excepcion IO
     * @param e Excepcion lanzada por el sistema
     */
    public void errorTransferenciaBaja(IOException e){
        System.err.println("ErrorHandler_Drep: Se ha producido un " +
                "error no esperado en la transferencia (Comando Baja)");
    }

    /**
     * Error intentando iniciar la sesion de un Drep
     */
    public void ErrorNewDrep(){
        System.err.println("Intentando volver a iniciar la sesion drep....");
        this.control.iniciarSesion();
    }

    //-------------Protocolo----------------------------

    /**
     * Recibimos un mensaje de error por parte del dmon
     */
    public void protocolErrorNewDrep(){
        System.err.println("ProtocolHandler_Drep: No ha sido posible" +
                " realizar su solicitud newDrep (Bad-Request)");
    }

    /**
     * Recibimos un mensaje de error por parte del drep
     */
    public void protocolErrorDisconnectDrep(){
        System.err.println("ProtocolHandler_Drep: No ha sido posible" +
                " realizar su solicitud disconnectDrep (Bad-Request)");
    }

    /**
     * Devuelve un mensaje de error cuando el puerto introducido en la línea de
     * comandos es inválido.
     *
     * @param puerto    el puerto inválido introducido
     */
    public void puertoInvalido(int puerto) {
        System.err.println("ErrorHandler_Drep: Puerto "+puerto+" Inválido: " +
                "Debe ser mayor a 1023 y menor que 65536");
        System.exit(-1);
    }
}
